﻿#region [AccelerometerSimulator Using Statements]
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.ServiceModel;
using AccelerometerWP7ClassLibrary.AccelerometerService;
using System.Threading;
#endregion

namespace AccelerometerWP7ClassLibrary
{
    /// <summary>
    /// Simulates the Accelerometer Class provided by the Windows Phone 7 dev tools
    /// </summary>
    public class AccelerometerSimulator
    {
        #region [AccelerometerSimulator Fields]
        private DispatcherTimer _pollingTimer;
        private AccelerometerServiceClient _accelerometerService;
        #endregion

        #region [AccelerometerSimulator Events]
        public delegate void EventHandler<AccelerometerReadingEventArgs>(object sender, AccelerometerReadingEventArgs e);
        public event EventHandler<AccelerometerSimulatorReadingEventArgs> ReadingChanged;
        #endregion

        #region [AccelerometerSimulator Constructor]
        /// <summary>
        /// AccelerometerSimulator Constructor
        /// </summary>
        public AccelerometerSimulator()
        {
            _pollingTimer = new DispatcherTimer();
            _pollingTimer.Tick += new EventHandler(AccelerometerPollingHandler);
            /*polling every 50 ms*/
            _pollingTimer.Interval = new TimeSpan(0, 0, 0, 0, 50);

            BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
            EndpointAddress endpointAddress = new EndpointAddress("http://localhost:8731/AccelerometerServer/");
            _accelerometerService = new AccelerometerServiceClient(basicHttpBinding,endpointAddress);
            _accelerometerService.DownloadAccelDataCompleted += new System.EventHandler<DownloadAccelDataCompletedEventArgs>(accelService_DownloadAccelDataCompleted);
        }
        #endregion

        #region [AccelerometerSimulator EventHandlers]
        /// <summary>
        /// EventHandler triggered when it's time to poll the server for
        /// acceleration info
        /// </summary>
        /// <param name="sender">Who triggered the event</param>
        /// <param name="e">Default EventArgs</param>
        private void AccelerometerPollingHandler(object sender, EventArgs e)
        {
            _accelerometerService.DownloadAccelDataAsync();   
        }

        /// <summary>
        /// EventHandler triggered when we get acceleration info from the server
        /// </summary>
        /// <param name="sender">Who triggered the event</param>
        /// <param name="e">
        /// DownloadAccelDataCompletedEventArgs where:
        /// e.Result is a XYZData struct and the struct fields 
        /// X, Y and Z correspond to the acceleration in the
        /// X, Y and Z axis.
        /// </param>
        private void  accelService_DownloadAccelDataCompleted(object sender, DownloadAccelDataCompletedEventArgs e)
        {
            XYZData accelData = e.Result;

            if(ReadingChanged != null)
                ReadingChanged(this, new AccelerometerSimulatorReadingEventArgs(accelData.X, accelData.Y, accelData.Z));
        }
        #endregion

        #region[AccelerometerSimulator Public Methods]
        /// <summary>
        /// Starts listening for acceleration info
        /// </summary>
        public void Start()
        {
            _pollingTimer.Start();
        }

        /// <summary>
        /// Stops listening for acceleration info
        /// </summary>
        public void Stop()
        {
            _pollingTimer.Stop();
        }
        #endregion
    }

    #region [AccelerometerSimulator's ReadingChanged event EventArgs]
    /// <summary>
    /// This class represents the arguments used in the event ReadingChanged
    /// </summary>
    public class AccelerometerSimulatorReadingEventArgs : EventArgs
    {
        #region [AccelerometerReadingEventArgs Fields]
        private double _x;
        private double _y;
        private double _z;
        #endregion

        #region [AccelerometerReadingEventArgs Properties]
        /// <summary>
        /// Acceleration on the X axis
        /// </summary>
        public double X 
        { 
            get { return _x; }
        }

        /// <summary>
        /// Acceleration on the Y axis
        /// </summary>
        public double Y 
        { 
            get { return _y; }
        }

        /// <summary>
        /// Acceleration on the Z axis
        /// </summary>
        public double Z 
        { 
            get { return _z; }
        }
        #endregion

        #region [AccelerometerReadingEventArgs Constructor]
        /// <summary>
        /// AccelerometerReadingEventArgs Constructor
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        public AccelerometerSimulatorReadingEventArgs(double x, double y, double z)
        {
            this._x = x;
            this._y = y;
            this._z = z;
        }
        #endregion
    }
    #endregion
}
